package com.csair.dao;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Service("genericDao")
public class GenericDao {

	private static int MAX_CACHE_SIZE = 200;
	@PersistenceContext
	private EntityManager em;
	
	private Map<Class<?>, SimpleJpaRepository> cache = new CacheHaspMap();
	
	public <T> T save(T entity, Class<T> entityClass) {
		JpaEntityInformation<T, ?> entityInfomation = JpaEntityInformationSupport.getMetadata(entityClass, em);
		if(entityInfomation.isNew(entity)) {
			em.persist(entity);
			em.flush();
			return entity;
		} else {
			T class_t = em.merge(entity);
			em.flush();
			return class_t;
		}
	}
	
	public <T, ID extends Serializable> T findOne(ID id, Class<T> entityClass) {
		return getSimpleJpaRepository(entityClass).findOne(id);
	}
	
	public <T, ID extends Serializable> void delete(ID id, Class<T> entityClass) {
		getSimpleJpaRepository(entityClass).delete(id);
	}
	
	public <T> List<T> findAll(Class<T> entityClass) {
		return getSimpleJpaRepository(entityClass).findAll();
	} 
	
	private <T,ID extends Serializable> SimpleJpaRepository<T, ID> getSimpleJpaRepository(Class<T> entityClass) {
		if(cache.containsKey(entityClass)) {
			return cache.get(entityClass);
		}
		
		SimpleJpaRepository simpleJpaRepository = new SimpleJpaRepository(JpaEntityInformationSupport.getMetadata(entityClass, em), em);
		cache.put(entityClass, simpleJpaRepository);
		return simpleJpaRepository;
	}
	
	private static class CacheHaspMap extends LinkedHashMap<Class<?>, SimpleJpaRepository> {
		protected boolean removeEldestEntry(Map.Entry eldest) {
			return size() > MAX_CACHE_SIZE;
		}
	}
}
